<script setup lang="ts">
import {onMounted, reactive, ref, watch} from "vue";
import {userStore} from "../../store";
import {Direction, GameOption, GameStatus, Map, Snake} from "./snake.ts";
import {ElMessage} from "element-plus";

const store = userStore()
const mapCanvas = ref<HTMLCanvasElement>()
const snakeCanvas = ref<HTMLCanvasElement>()
const foodCanvas = ref<HTMLCanvasElement>()
const color = ref(['#dbe2ef', "#f6f6f6"])
const game = reactive({
    isStart: false,
    score: 0,
    speed: 300,
    time: 0,
    timeFormat: (time: number) => {
        const hour = Math.floor(time / 3600000).toString().padStart(2, '0')
        const minute = Math.floor(time / 60000).toString().padStart(2, '0')
        const second = Math.floor((time / 1000)).toString().padStart(2, '0')
        return `${hour}:${minute}:${second}`
    }
})

const gameOption: GameOption = {
    width: 0,
    height: 0,
    mapColor: color.value,
    speed: 100,
    offset: [0, 0],
    cellNumber: 30,
    cellSize: 20,
    foodColor: '#30e3ca'
}

let map: Map | null = null
const snake = ref<Snake | null>(null)

onMounted(() => {
    // 绘制画面
    if (!mapCanvas.value) {
        console.log('Error');
        return
    }
    const parentDiv = mapCanvas.value.parentElement;
    if (parentDiv) {
        mapCanvas.value.width = parentDiv.clientWidth;
        mapCanvas.value.height = parentDiv.clientHeight;
        snakeCanvas.value.width = parentDiv.clientWidth;
        snakeCanvas.value.height = parentDiv.clientHeight;
        foodCanvas.value.width = parentDiv.clientWidth;
        foodCanvas.value.height = parentDiv.clientHeight;
        gameOption.width = mapCanvas.value.width
        gameOption.height = mapCanvas.value.height
        gameOption.offset = [
            Math.floor((parentDiv.clientWidth - 20 * 30) / 2),
            Math.floor((parentDiv.clientHeight - 20 * 30) / 2)
        ]
    }
    const mapContext = mapCanvas.value.getContext('2d');
    const snakeContext = snakeCanvas.value.getContext('2d');
    const foodContext = foodCanvas.value.getContext('2d');
    map = new Map(gameOption, mapContext)
    map.draw()
    snake.value = new Snake(gameOption, snakeContext, foodContext)
    watch(() => [snake.value?.gameStatus, snake.value?.score, snake.value?.time],
        (val: any) => {
            if (val[0] === GameStatus.STOP && game.isStart) {
                ElMessage.warning('游戏结束')
            }
            game.isStart = val[0] !== GameStatus.STOP
            game.score = val[1]
            game.time = val[2]

        }, {deep: true, immediate: true}
    )
})


watch(() => [store.isDarkMode], async () => {
    color.value = !store.isDarkMode ? ['#dbe2ef', "#f6f6f6"] : ['#212121', "#3e4149"]
    map.draw(color.value)
    gameOption.foodColor = !store.isDarkMode ? '#30e3ca' : '#0d7377'
}, {deep: true});

const handleGameStart = () => {
    game.isStart = !game.isStart
    if (game.isStart) {
        snake.value.start()
        addEventListener('keydown', (e) => {
            if (e.key === 'ArrowUp' || e.key === 'w' || e.key === 'W') {
                snake.value.setDirection(Direction.UP)
            } else if (e.key === 'ArrowDown' || e.key === 's' || e.key === 'S') {
                snake.value.setDirection(Direction.DOWN)
            } else if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'A') {
                snake.value.setDirection(Direction.LEFT)
            } else if (e.key === 'ArrowRight' || e.key === 'd' || e.key === 'D') {
                snake.value.setDirection(Direction.RIGHT)
            }
        })
        game.score = snake.value.score
    } else {
        snake.value.pause()
    }
}

const handleGameRestart = () => {
    game.isStart = true
    game.score = 0
    game.time = 0
    snake.value.restart()
    addEventListener('keydown', (e) => {
        if (e.key === 'ArrowUp' || e.key === 'w' || e.key === 'W') {
            snake.value.setDirection(Direction.UP)
        } else if (e.key === 'ArrowDown' || e.key === 's' || e.key === 'S') {
            snake.value.setDirection(Direction.DOWN)
        } else if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'A') {
            snake.value.setDirection(Direction.LEFT)
        } else if (e.key === 'ArrowRight' || e.key === 'd' || e.key === 'D') {
            snake.value.setDirection(Direction.RIGHT)
        }
    })
}

</script>

<template>
    <div style="height: 50px; width: 100%; text-align: center; margin-bottom: 8px">
        <el-text tag="b" style="font-size: 35px">贪吃蛇大作战</el-text>
    </div>
    <el-card style="height: calc(100% - 60px)" body-style="height: calc(100% - 40px)">
        <el-row :gutter="10" style="height: 100%">
            <el-col :span="19">
                <div style="height: 10%; width: 100%; display: flex; justify-content: space-around">
                    <el-text tag="b" style="font-size: 20px">得分：{{ game.score }}</el-text>
                    <el-text tag="b" style="font-size: 20px">速度：{{ game.speed }}</el-text>
                    <el-text tag="b" style="font-size: 20px">时间：{{ game.timeFormat(game.time) }}</el-text>
                </div>
                <div style="height: 90%; width: 100%; position:relative;">
                    <!--                    游戏界面区域-->
                    <canvas ref="mapCanvas" class="canvas" style="z-index: 1"/>
                    <canvas ref="snakeCanvas" class="canvas" style="z-index: 2"/>
                    <canvas ref="foodCanvas" class="canvas" style="z-index: 3"/>
                </div>
            </el-col>
            <el-col :span="5" style="height: 100%">
                <!--                配置区-->
                <el-card style="height: 100%">
                    <el-button
                        style="width: 100%"
                        type="primary" size="large" @click="handleGameStart">
                        {{ game.isStart ? '暂停' : '开始' }}
                    </el-button>
                    <el-button
                        style="width: 100%; margin-top: 10px; margin-left: 0"
                        type="primary" size="large" @click="handleGameRestart">
                        重新开始
                    </el-button>
                    <div style="width: 100%; display: flex; justify-content: space-between; margin-top: 10px;">
                        <el-text style="font-size: 16px">速度</el-text>
                        <el-select v-model="game.speed" style="width: 100px">
                            <el-option label="300" value="300"></el-option>
                            <el-option label="200" value="200"></el-option>
                            <el-option label="100" value="100"></el-option>
                        </el-select>
                    </div>
                    <el-text style="font-size: 25px; width: 100%; text-align: center; display: block">战绩</el-text>
                    <el-table
                        :data="[]"
                        style="width: 100%; height: calc(100% - 100px)"
                        border
                        stripe
                        highlight-current-row
                        :row-style="{color: '#212121'}"
                        :header-cell-style="{color: '#212121'}"
                    >
                        <el-table-column type="selection"/>
                        <el-table-column prop="datetime" label="时间日期"/>
                        <el-table-column prop="score" label="得分"/>
                    </el-table>
                </el-card>
            </el-col>
        </el-row>
    </el-card>
</template>

<style scoped lang="css">
.canvas {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
}
</style>